/*
  Copyright (C) 2011 Zhao Ming(zhao.ming29@gmail.com)

  All rights reserved.

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU Lesser General Public License version 2.1, as
  published by the Free Software Foundation.  This program is
  distributed in the hope that it will be useful, but WITHOUT ANY
  WARRANTY; without even the implied warranty of MERCHANTABILITY or
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
  License for more details.

  You should have received a copy of the GNU Lesser General Public License
  along with this program; if not, see <http://www.gnu.org/licenses/>.
*/

#include "LRCReceiver.h"
#include <memory.h>
#include <math.h>
#include <stdio.h>

int CLRCReceiver::D[] = {64,   4,   8,   2,  16,   1,  32};
int CLRCReceiver::W[] = {-1,  -1,  -1,   1,   1,   1,   1};

CLRCReceiver::CLRCReceiver( int addrA, int addrB, int maxS, int tP )
{
	int i,j,c;
	
	maxSeg = maxS;
	ghgsI[0] = new GHGS(7,D,W);
	ghgsQ[0] = new GHGS(7,D,W);
	ghgsI[1] = new GHGS(7,D,W);
	ghgsQ[1] = new GHGS(7,D,W);
	
	len = maxSeg*640;
	
	MacAddr *addr = new MacAddr( addrA, addrB );
	aWash = new CWash( 9 );
	rBuf = new CRecvBuf( (128+len)*4, (128+len)*4 );
	iMask = new int[len];
	char *mask = new char[len/8];
	addr->genCode( mask, len );
	for( i=0;i<maxSeg*640;i++ )
	{
		c = mask[i/8]>>(i%8);
		c &= 1;
		iMask[i]=1-2*c;
	}
	thresholdPilot = tP;
	washBuf = new int[512];
	nowTime = 0;
	skip = 0;
	delete addr;
	delete mask;
}

CLRCReceiver::~CLRCReceiver()
{
	int i;
	delete ghgsI[0];
	delete ghgsQ[0];
	delete ghgsI[1];
	delete ghgsQ[1];
	delete aWash;	
	delete iMask;
	delete rBuf;
	delete washBuf;
}

int CLRCReceiver::recv( char *t, int k, struct Message res[] )
{
	if( rBuf->put(t,k)!=0 )
		return -1;
	int num=0;
	int i,j;
	res[num].len=0;
	char *xcorr;
	while( rBuf->get(&xcorr,1024)==0 )
	{
		int offset = 0;
		int pos;
		int T;
		for( pos=0;pos<1024;pos+=2 )
		{
			nowTime++;
			offset=pos>>1;
			pilot[0].i = nowPilot.i;
			pilot[0].q = nowPilot.q;
			ghgsI[offset&1]->doit( (int)xcorr[pos],nowPilot.i,T );
			ghgsQ[offset&1]->doit( (int)xcorr[pos+1],nowPilot.q,T );
			int pow=power(pilot[0]);
			if( skip>0 ) skip--;
			if( pow>thresholdPilot && power(nowPilot)<pow && skip == 0 )
			{	
				offset = pos+2;
				for( j=0;j<MAXSEG;j++ )
				{
					rBuf->maskSum( 
						offset+640*4*j+512*4, 
						pilot[j+1].i, 
						pilot[j+1].q, 
						iMask+512+640*j, 
						128 );
				}
				pow+=power(pilot[j+1]);
				if( pow>(2*MAXSEG+1)*thresholdPilot )
				{
					int errorFlag = 0;
					for( res[num].len=0;res[num].len<MAXSEG;res[num].len++ )
					{
						carrier(res[num].len);
						for( j=0;j<4;j++ )
						{
							rBuf->rolOut( 
								washBuf+128*j,
								offset+640*4*res[num].len+j*512,
								mid[j].i,mid[j].q,
								iMask+640*res[num].len+128*j,
								128);
							//printf("%d %d\n",mid[j].i,mid[j].q);
						}
						int max;
						res[num].mes[res[num].len]=aWash->rDec(washBuf,max);
						//printf("%d\n",max);
						if( res[num].mes[res[num].len]==-1 )
							errorFlag=1;
						res[num].time = nowTime;
					}
					if( errorFlag==0 )
					{
						num++;
						skip = 10;
					}
				}
			}
		}
		if( num>MAXMES )
			break;
	}	
	return num;
}

void CLRCReceiver::carrier( int p )
{
	int i;
	int I = pilot[p+1].i - pilot[p].i;
	int Q = pilot[p+1].q - pilot[p].q;
	for( i=0;i<4;i++ )
	{
		mid[i].i=pilot[p].i*5+I*(i+1);
		mid[i].q=pilot[p].q*5+Q*(i+1);
		double ai = mid[i].i;
		double aq = mid[i].q;
		double s = sqrt(ai*ai+aq*aq)/256.;
		ai/=s;
		aq/=s;
		mid[i].i=ai;
		mid[i].q=aq;	
	}
}

#ifdef RECVTEST
#include "LRCTransmiter.h"

#include<stdio.h>
#include<memory.h>
struct Message message[MAXMES];

int main()
{
	int i,j,k;
	int frameLen = (128+2*640);
	char *tBuf = new char[frameLen*4];
	char *t = new char[frameLen/8];
	CLRCTransmiter *aT = new CLRCTransmiter(1,1,2);
	CLRCReceiver *aR = new CLRCReceiver( 1,1,2,32 );
	int c;
	for( i=0;i<1024*20;i++ )
	{
		int mes[2]={i&0x3ff,i>>10};
		aT->send(t,	mes, 2);
		memset(tBuf,0,frameLen*4);
		for( j=0;j<frameLen;j++ )
		{
			c = t[j/8]>>(j%8);
			c&=1;
			tBuf[4*j]=1-2*c;
		}
		
		int num = aR->recv( tBuf, frameLen*4, message );
/*		
		for( j=0;j<num;j++ )
		{
			for( k=0;k<message[j].len;k++ )
				printf("%d ",message[j].mes[k]);
			printf("\n");	
		}
*/
	}
	delete tBuf;
	delete t;
	delete aT;
	delete aR;
	return 0;
}

#endif
